/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = sip_core.h                                         */
/*  NOTE      =                                                    */
/*  DATE      = 2015/07/07 by songbb                               */
/*******************************************************************/

#ifndef __SIP_CORE_H_
#define __SIP_CORE_H_

#include "frlist.h"
#include "frhash2.h"
#include "frstr.h"
#include "frreport_comm.h"

#include "conntrack.h"
#include "module.h"
#include "frbyte_buffer.h"

typedef enum __em_req_method {
    SIP_METHOD_TYPE_UNKNOWN = 0,
    SIP_METHOD_TYPE_INVITE,
    SIP_METHOD_TYPE_ACK,
    SIP_METHOD_TYPE_BYE,
    SIP_METHOD_TYPE_CANCEL,
    SIP_METHOD_TYPE_OPTIONS,
    SIP_METHOD_TYPE_REGISTER,
    SIP_METHOD_TYPE_PRACK,
    SIP_METHOD_TYPE_SUBSCRIBE,
    SIP_METHOD_TYPE_NOTIFY,
    SIP_METHOD_TYPE_PUBLISH,
    SIP_METHOD_TYPE_INFO,
    SIP_METHOD_TYPE_REFER,
    SIP_METHOD_TYPE_MESSAGE,
    SIP_METHOD_TYPE_UPDATE
} Sip_req_method;

/*
 * L7session_sip 用于存放SIP私有的session数据，对应L7_session的p_session_private变量
 */
typedef struct __st_L7session_sip
{
    unsigned long long ull_error_nums;
    unsigned long long ull_unfinshed_fragmented_packets;
    struct timeval st_registered_timestamp;
    char *p_server;

} L7session_sip;

/**
 * 分片的状态
 */
typedef enum __em_fragment_state {
    APM_SIP_FRAGMENT_INIT,
    APM_SIP_FRAGMENT_NEED_NEXT_REQ_PACKET,
    APM_SIP_FRAGMENT_NEED_NEXT_RESP_PACKET
} Sip_fragment_state;

/**
 * SIP数据包结构体
 */
typedef struct __st_L7_sip_packet
{
    Sip_fragment_state fragment_state;  /* 当前的分片状态 */
    Frbyte_Packet *p_st_packet;         /* 组包完成的数据 */
    int i_is_sip_req;                   /* SIP协议层的请求 */
    unsigned int ui_length;             /* 完整的一个SIP请求或者响应的长度 */
    unsigned int ui_content_length;     /* SIP message body的长度*/
    char *p_req_method;
    Sip_req_method em_req_method;
    struct timeval st_timestamp_first;  /* 第一个请求的分片包的时间 */
    struct timeval st_timestamp_last;   /* 最后一个请求的分片包的时间 */
} L7_sip_packet;

/**
 * SIP一次交互过程，一次REGISTER或者一次INVITE过程，从request发起开始到收到一个非临时性应答为止
 */
typedef struct __st_L7_sip_stmt
{
    Sip_req_method em_req_method;
    int i_is_register;
    struct timeval st_req_end_timestamp;
    struct timeval st_resp_start_timestamp;
    unsigned long ul_resp_server_time_us;
    unsigned long ul_resp_bytes;
    Frlist_header *p_report_comm;        /* 用于临时存储report的公共部分数据 */
    Frlist_header *p_report_req;         /* 用于临时存储report的请求部分数据 */

    char *p_username;

    unsigned long ul_invite_begin_timestamp;
    char *p_uri;
    unsigned int *p_ui_media_src_ip;
    int i_media_src_ip_len;
    unsigned int *p_ui_media_dst_ip;
    int i_media_dst_ip_len;
    int *p_i_media_src_port;
    int i_media_src_port_len;
    int *p_i_media_dst_port;
    int i_media_dst_port_len;
    unsigned short us_proto;
} L7_sip_stmt;

/**
 * SIP私有结构体
 */
typedef struct __st_L7session_sip_private
{
    L7session_sip *p_st_sess;            /* session数据 */
    Frhash_header *p_hash_stmt;          /* 按Via字段中的branch值建立hash */
    L7_sip_packet *p_st_sip_packet;      /* 当前处理中的SIP数据包 */
    L7_session *p_st_session;            /* 指向父级的L7_session结构体 */
    struct timeval st_timestamp;
} L7session_sip_private;

void sip_core_add_unfinshed_fragmented_packets(L7session_sip *p_st_sess);

int sip_detect(Conntrack *p_st_conn
            , Apm_packet *p_st_packet);

int sip_analyze(Conntrack *p_st_conn
                , Apm_packet *p_analyze_in
                , Frhash_header *p_st_hash_report);

int sip_session_destory(void *p_st_session_private_in);

#endif
